home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mjovesrc.zoo / jove.c < prev    next >
C/C++ Source or Header  |  1992-09-16  |  30KB  |  1,588 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* Contains the main loop initializations, and some system dependent
  9.    type things, e.g. putting terminal in CBREAK mode, etc. */
  10.  
  11. #include "jove.h"
  12. #include "fp.h"
  13. #include "termcap.h"
  14. #include "ctype.h"
  15. #include "chars.h"
  16. #include "disp.h"
  17. #include "re.h"    /* for find_tag() */
  18. #include "rec.h"
  19. #ifdef    IPROCS
  20. # include "iproc.h"
  21. #endif
  22.  
  23. #ifdef SCO
  24. #undef TIOCGWINSZ
  25.  
  26. #include <sys/stream.h>
  27. #include <sys/ptem.h>
  28. #endif
  29.  
  30. #ifdef    MAC
  31. # include "mac.h"
  32. #else
  33. # ifdef    STDARGS
  34. #  include <stdarg.h>
  35. # else
  36. #  include <varargs.h>
  37. # endif
  38. # include <stat.h>
  39. #endif
  40.  
  41. #include <signal.h>
  42. #include <errno.h>
  43.  
  44. #ifdef    MSDOS
  45. # include <process.h>
  46. #endif    /* MSDOS */
  47.  
  48. #ifndef    MAC
  49. # include <fcntl.h>
  50. #endif
  51.  
  52. #ifdef    MSDOS
  53. private    void    break_off proto((void)),
  54.         break_rst proto((void));
  55. #endif
  56.  
  57. #ifdef    MAC
  58. # define    WINRESIZE    1
  59. #else
  60. # ifdef    TIOCGWINSZ
  61. #   ifdef    SIGWINCH
  62. #     define    WINRESIZE    1
  63. #   endif
  64. # endif
  65. #endif
  66.  
  67. private void
  68.     DoKeys proto((bool firsttime));
  69.  
  70. #ifdef    MSDOS
  71. extern
  72. #else
  73. private
  74. #endif
  75.     void
  76.     UnsetTerm proto((char *)),
  77.     do_sgtty proto((void));
  78.  
  79. /* Various tty state structures.
  80.  * Each is an array, subscripted by one of "OFF" or "ON".
  81.  */
  82.  
  83. #ifdef    UNIX
  84.  
  85. #include "ttystate.h"
  86.  
  87. # ifdef    TIOCSLTC
  88. struct ltchars    ls[2];
  89. # endif    /* TIOCSLTC */
  90.  
  91. # ifdef    TIOCGETC
  92. struct tchars    tc[2];
  93. # endif
  94.  
  95. # ifdef    PASS8            /* use pass8 instead of raw for meta-key */
  96. private int    lmword[2];        /* local mode word */
  97. # endif
  98.  
  99. # ifdef    BRLUNIX
  100. struct sg_brl    sg[2];
  101. #endif
  102. #ifdef TERMIO
  103. struct termio    sg[2];
  104. #endif
  105. #ifdef TERMIOS
  106. struct termios    sg[2];
  107. #endif
  108. #ifdef SGTTY
  109. struct sgttyb    sg[2];
  110. #endif
  111.  
  112. # ifdef    BIFF
  113. private struct stat    tt_stat;    /* for biff */
  114. #  ifndef    BSD4_2
  115. private char    *tt_name = NULL;        /* name of the control tty */
  116. extern char    *ttyname();        /* for systems w/o fchmod ... */
  117. #  endif
  118. private bool    dw_biff = NO;        /* whether or not to fotz at all */
  119. # endif    /* BIFF */
  120. #endif    /* UNIX */
  121.  
  122. bool    errormsg;
  123. char    NullStr[] = "";
  124. jmp_buf    mainjmp;
  125.  
  126.  
  127. #ifdef    MSDOS
  128. # define SIGHUP    99
  129. #endif    /* MSDOS */
  130.  
  131. /* finish() does not return, so it is funny that it returns a non-void
  132.  * result.  This is because most systems claim that signal(2) deals
  133.  * with functions of type int ().  ANSI changes this: the function
  134.  * type must be void (int).  This bridge must soon be crossed.
  135.  */
  136. SIGRESULT
  137. finish(code)
  138. int    code;
  139. {
  140.     int save_errno = errno;    /* Subtle, but necessary! */
  141.     static int    Crashing = 0;    /* we are in the middle of crashing */
  142.     bool    CoreDump = (code != 0 && code != SIGHUP),
  143.         DelTmps = YES;        /* Usually we delete them. */
  144.  
  145.     if (code == SIGINT) {
  146.         char    c;
  147. #ifdef    PIPEPROCS
  148.         int    started;
  149. #endif
  150. #ifndef    MENLO_JCL
  151.         (void) signal(code, finish);
  152. #endif
  153.         f_mess("Abort (Type 'n' if you're not sure)? ");
  154. #ifndef    MSDOS
  155. # ifdef    PIPEPROCS
  156.         started = kbd_stop();
  157. # endif
  158. #ifdef    SYSV
  159.         if (read(0, (UnivPtr) &c, (size_t) 1) != 1)
  160. #endif
  161.             (void) read(0, (UnivPtr) &c, (size_t) 1);
  162. # ifdef    PIPEPROCS
  163.         if (started)
  164.             (void) kbd_strt();
  165. # endif
  166. #else    /* MSDOS */
  167.         c = getrawinchar();
  168. #endif    /* MSDOS */
  169.         message(NullStr);
  170.         if ((c & 0377) != 'y') {
  171.             redisplay();
  172.             errno = save_errno;
  173.             SIGRETURN;
  174.         }
  175.     }
  176.     DisabledRedisplay = YES;
  177. #ifndef    MAC
  178.     UnsetTerm(NullStr);
  179. #endif
  180. #ifdef    PIPEPROCS
  181.     kbd_kill();        /* kill the keyboard process */
  182. #endif
  183. #ifndef    MSDOS
  184.     if (code != 0) {
  185.         if (!Crashing) {
  186.             Crashing = YES;
  187.             lsave();
  188.             SyncRec();
  189.             writef("JOVE CRASH!! (code %d): %s\n", code,
  190.                    strerror(errno));
  191.             if (ModBufs(YES)) {
  192.                 writef("Your buffers have been saved.\n");
  193.                 writef("Use \"jove -r\" to have a look at them.\n");
  194.                 DelTmps = NO;    /* Don't delete anymore. */
  195.             } else
  196.                 writef("You didn't lose any work.\n");
  197.         } else
  198.             writef("\r\nYou may have lost your work!\n");
  199.     }
  200. #endif    /* MSDOS */
  201.     flushscreen();
  202.     if (DelTmps) {
  203. #ifdef    PTYPROCS
  204.         (void) signal(SIGCHLD, SIG_IGN);
  205. #endif
  206.         tmpremove();
  207. #ifndef    MSDOS
  208.         recremove();
  209. #endif    /* MSDOS */
  210.     }
  211. #ifdef    UNIX
  212.     if (CoreDump)
  213.         abort();
  214. #ifdef    PROFILING
  215.     exit(0);
  216. #else
  217.     _exit(0);
  218. #endif
  219. #else    /* !UNIX */
  220. #ifdef    MSDOS
  221.     break_rst();    /* restore previous ctrl-c handling */
  222. #endif
  223.     exit(0);
  224. #endif    /* !UNIX */
  225.     /*NOTREACHED*/
  226. }
  227. private char    smbuf[20],
  228.         *bp = smbuf;
  229.  
  230. private int    nchars = 0;
  231.  
  232. private char    peekbuf[10],
  233.         *peekp = peekbuf;
  234.  
  235. #if    defined(SYSV) || defined(M_XENIX)
  236.  
  237. #define    NONBLOCKINGREAD    1
  238.  
  239. private void
  240. setblock(fd, on)    /* turn blocking on or off */
  241. register int    fd;
  242. bool    on;
  243. {
  244.     static int blockf, nonblockf;
  245.     static bool    first = TRUE;
  246.  
  247.     if (first) {
  248.     int flags;
  249.  
  250.     first = FALSE;
  251.     if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
  252.         finish(SIGHUP);
  253.     blockf = flags & ~O_NDELAY;    /* make sure O_NDELAY is off */
  254.     nonblockf = flags | O_NDELAY;    /* make sure O_NDELAY is on */
  255.     }
  256.     if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1)
  257.     finish(SIGHUP);
  258. }
  259.  
  260. #endif    /* defined(SYSV) || defined(M_XENIX) */
  261.  
  262. private int
  263. Peekc()
  264. {
  265.     return peekp == peekbuf? EOF : *--peekp & 0377;
  266. }
  267.  
  268. void
  269. Ungetc(c)
  270. int    c;
  271. {
  272.     if (peekp != &peekbuf[(sizeof peekbuf) - 1])
  273.         *peekp++ = c;
  274. }
  275.  
  276. bool    InputPending = NO;
  277.  
  278. char    *Inputp = NULL;
  279.  
  280. #ifdef    PTYPROCS
  281.  
  282. /* Warning! This code requires 32-bit ints.  A thoroughly obscure mess --
  283.    ffs() as a three-line "for" loop.   This is what you get for not
  284.    including ffs() in the libs.  -- Doug
  285. */
  286. #ifdef MiNT
  287. int
  288. ffs(int i)
  289. {
  290.     int z;
  291.  
  292.     for (z = 1; z <= (sizeof(int) * 8); z++)
  293.         if (i & ~(0xFFFFFFFF >> z))
  294.             return ((sizeof(int) * 8) - --z);
  295. }
  296. #endif
  297.  
  298. int
  299. jgetchar()
  300. {
  301.     long        reads;
  302.     register int    tmp,
  303.             nfds;
  304.     int        c;
  305.  
  306.     if (nchars <= 0) {
  307.         /* Get a character from the keyboard, first checking for
  308.            any input from a process.  Handle that first, and then
  309.            deal with the terminal input. */
  310.         do {
  311.             do {
  312.                 reads = global_fd;
  313.                 nfds = select(32, &reads, (long *)NULL, (long *)NULL, (struct timeval *)NULL);
  314.             } while (nfds < 0 && errno == EINTR);
  315.  
  316.             if (nfds == -1)
  317.                 complain("\rerror in select %ld: %s", global_fd, strerror(errno));
  318.             else {
  319.                 if (reads & 01) {
  320. /* This is where I replaced read() with my own command to get characters
  321.    from the BIOS.  This allowed me to implement all the Atari special keys.
  322.    Recent developments in MiNT have rendered all of this obsolete, and it
  323.    is one thing I will eventually replace.  If you, the reader, decide to
  324.    undertake this yourself, please email a copy of your code to:
  325.    dstailey@leidecker.gsfc.nasa.gov   -- Doug
  326. */
  327. #ifdef MiNT
  328.                     *smbuf = jgetkey();
  329.                     nchars = 1;
  330. #else
  331.                     nchars = read(0, (UnivPtr) smbuf, sizeof(smbuf));
  332. #endif MiNT
  333.                     reads &= ~01;
  334.                     nfds -= 1;
  335.                 }
  336.                 while (nfds--) {
  337.                     tmp = ffs(reads) - 1;
  338.                     read_proc(tmp);
  339.                     reads &= ~(1L << tmp);
  340.                 }
  341.             }
  342.         } while (nchars <= 0);
  343.  
  344.         if (nchars <= 0)
  345.             finish(SIGHUP);
  346.  
  347.         bp = smbuf;
  348.         InputPending = (nchars > 1);
  349.     }
  350.  
  351.     if (((c = *bp) & 0200) && MetaKey) {
  352.         *bp = (c & CHARMASK);
  353.         return '\033';
  354.     }
  355.     nchars -= 1;
  356.     return *bp++ & 0377;
  357. }
  358.  
  359. #else    /* !PTYPROCS */
  360.  
  361. int
  362. jgetchar()
  363. {
  364.     register int    c;
  365.     struct header {
  366.         int    pid;
  367.         int    nbytes;
  368.     } header;
  369.  
  370. normal:
  371.     if (nchars <= 0) {
  372.         bp = smbuf;
  373. #ifdef    MSDOS
  374.         *bp = getrawinchar();
  375.         nchars = 1;
  376. #else    /* !MSDOS */
  377. # ifdef    IPROCS
  378.         if (NumProcs > 0) {
  379.             for (;;) {
  380.                 size_t    n = f_readn(ProcInput, (char *) &header,
  381.                         sizeof(header));
  382.  
  383.                 if (n != sizeof(header)) {
  384.                     raw_complain("\r\nError reading kbd process, expected %d, got %d bytes\r\n", sizeof header, n);
  385.                     finish(SIGHUP);
  386.                 }
  387.                 /* data is from the keyboard process */
  388.                 if (header.pid == kbd_pid) {
  389.                     nchars = f_readn(ProcInput, smbuf, header.nbytes);
  390.                     if (nchars != header.nbytes) {
  391.                         raw_complain("\r\nError reading kbd process, expected %d, got %d bytes.\r\n", header.nbytes, nchars);
  392.                         finish(SIGHUP);
  393.                     }
  394.                     break;
  395.                 }
  396.                 read_proc(header.pid, header.nbytes);
  397.                 if (NumProcs == 0) {
  398.